package org.one.stone.soup.grfxML.plugin.text;

import java.awt.FontMetrics;
import java.awt.Graphics;
import java.util.StringTokenizer;

import org.one.stone.soup.grfxML.DataPoint;
import org.one.stone.soup.grfxML.DataString;
import org.one.stone.soup.grfxML.DataText;
import org.one.stone.soup.grfxML.DataTextArea;
import org.one.stone.soup.grfxML.GeometryText;
import org.one.stone.soup.grfxML.GrfxMLEngine;
import org.one.stone.soup.grfxML.plugin.SimplePlugin;
import org.one.stone.soup.grfxML.plugin.grfxMLCaster;
import org.one.stone.soup.mjdb.data.field.LockException;

public class Paginator extends SimplePlugin {

	public static final int ARG_SOURCE	=	0;
	public static final int ARG_BOUNDS	=	1;
	public static final int ARG_TARGET	=	2;

	DataText source = new DataText();
	DataPoint bounds = new DataPoint();
	
	DataTextArea[] target;
	private boolean processing = false;
	private boolean waitingProcessing = false;
/**
 * ShowInfo constructor comment.
 */
public Paginator(GrfxMLEngine engine) {
	super(engine);

}
/**
 * initialize method comment.
 */
public void initialize() {}
public void process()
{
	if(processing==true)
	{
		return;
	}
	processing = true;
	
	if(source.hasChanged())
	{
		waitingProcessing = true;
	}
		
	try{
		if(waitingProcessing)
		{
			paginate();
		}
	}
	catch(Exception e){
		e.printStackTrace();
	}
	
	processing = false;
}
public void register(org.one.stone.soup.mjdb.data.field.DataLinker store)
{
	source	=	grfxMLCaster.cast(source,getArg(source,ARG_SOURCE,store));
	bounds	=	grfxMLCaster.cast(bounds,getArg(bounds,ARG_SOURCE,store));
	
	int areas = getData().size()-ARG_TARGET;
	target = new DataTextArea[areas];
	for(int loop=0;loop<areas;loop++)
	{
		target[loop] = new DataTextArea();
		target[loop] = grfxMLCaster.cast(target[loop],getArg(target[loop],loop+ARG_TARGET,store));
	}
}
public void replace(org.one.stone.soup.mjdb.data.field.Field oldObj, org.one.stone.soup.mjdb.data.field.Field newObj)
{
	source	=	grfxMLCaster.replace(source,oldObj,newObj);
	bounds	=	grfxMLCaster.replace(bounds,oldObj,newObj);
	
	int areas = getData().size()-ARG_TARGET;
	for(int loop=0;loop<areas;loop++)
	{
		target[loop]	=	grfxMLCaster.replace(target[loop],oldObj,newObj);
	}
}
/**
 * stop method comment.
 */
public void stop() {}

private void paginate() throws LockException
{
	int textAreaCursor = 0;
	DataTextArea textArea = target[textAreaCursor];
	
	GeometryText textImpl = (GeometryText)textArea.getGeometry(getEngine());
	if(textImpl==null)
	{
		return;
	}
	FontMetrics fontMetrics = ((GeometryText)textArea.getGeometry(getEngine())).getFontMetrics();
	Graphics grfx = ((GeometryText)textArea.getGeometry(getEngine())).getGraphicsContext();
	
	if(fontMetrics==null || grfx==null)
	{
		return;
	}
	
	StringBuffer rawText = new StringBuffer();
	for(int loop=0;loop<source.size();loop++)
	{
		rawText.append( source.get(loop).getValue() );
	}
	
	String[] words = parseWords(rawText.toString());
	int wordCursor = 0;
		
	for(int loop=0;loop<words.length;loop++)
	{
		char c = words[loop].charAt(0);
			
		switch(c)
		{
			case ' ':
			case '\n':
			case '\t':
				break;
			case '\r':
				words[wordCursor] = words[loop];
				wordCursor++;
				break;
			default:
				words[wordCursor] = words[loop]+" ";
				wordCursor++;
		}
	}
		
	String[] newWords = new String[wordCursor];
	System.arraycopy(words,0,newWords,0,wordCursor);
	wordCursor = 0;
				
	int pageHeight = 0;
	StringBuffer line = new StringBuffer();
	int lineWidth = 0;
	
	textArea.getText().setEmpty();
	
	waitingProcessing = false;
	
	while(wordCursor<words.length)
	{
		while(wordCursor<words.length && pageHeight+fontMetrics.getHeight()<bounds.getValueY())
		{
			while(wordCursor<words.length && words[wordCursor].length()>1 && lineWidth+fontMetrics.getStringBounds(words[wordCursor],grfx).getWidth()<bounds.getValueX())
			{
				line.append(words[wordCursor]);
				lineWidth+=fontMetrics.getStringBounds(words[wordCursor],grfx).getWidth();
					
				wordCursor++;
			}
			if(wordCursor<words.length && words[wordCursor].length()==1)
			{
				textArea.getText().add( new DataString(line.toString()),this );
				pageHeight+=fontMetrics.getHeight();
					
				line = new StringBuffer();
				textArea.getText().add( new DataString(line.toString()),this );
				pageHeight+=fontMetrics.getHeight();
					
				line = new StringBuffer();
				lineWidth = 0;
				wordCursor++;
					
				continue;				
			}
			else if( wordCursor<words.length && fontMetrics.getStringBounds(words[wordCursor],grfx).getWidth()>bounds.getValueX() )
			{
				textArea.getText().add( new DataString("111"),this );
				pageHeight+=fontMetrics.getHeight();
				textArea.getText().add( new DataString("222"),this );
				pageHeight+=fontMetrics.getHeight();

				wordCursor++;
			}
			/*else if( wordCursor<words.length && splitWords)
			{
				if( words[wordCursor].length()>3 )
				{
					line.append( getSplit(grfx,fontMetrics,words,wordCursor,lineWidth) );
				}
			}*/
				
			textArea.getText().add( new DataString(line.toString()),this );
			line = new StringBuffer();
			lineWidth = 0;
				
			pageHeight+=fontMetrics.getHeight();
		}
			
		textAreaCursor++;
		if(textAreaCursor>=target.length)
		{
			return;
		}
		textArea = target[textAreaCursor];
		textArea.getText().setEmpty();
		pageHeight = 0;
	}
}

private String[] parseWords(String source) {

	String[] data;

	source = source.replace('\n',' ');
	StringTokenizer tokenizer = new StringTokenizer(source,"\r\t ",true);

	data= new String[tokenizer.countTokens()];
	int loop=0;
	while(tokenizer.hasMoreTokens())
	{
		data[loop] = tokenizer.nextToken();
		loop++;
	}
	
	return data;
}

}